了解useEffect之前,先來知道 何謂 副作用吧!
在日常生活中,我們常聽到「副作用」這個詞。例如,當我們服用藥物時,藥袋上可能會寫明該藥物的副作用,如嗜睡、頭痛或腸胃不適。雖然副作用通常被視為不良反應,但它們也可能帶來一些正面的影響,例如加快病情康復。
在程式中,副作用指的是在函式運行期間對外部環境的任何影響或變化。這些影響可能包括修改全域變數、手動更改 DOM 元素、執行 API 請求,甚至改變傳入參數。這些操作都會影響到函式外部的狀態,使程式變得難以預測和維護。
以下是一些常見的副作用操作:
// 修改全域變數或物件屬性
let count = 0;
function increment() {
count += 1; // 修改全域變數 count
}
increment();
console.log("全域變數 count 的值:", count); // 1
// 修改 DOM
function changeTitle(newTitle) {
document.title = newTitle; // 修改瀏覽器的標題
}
changeTitle("新標題");
// 執行 API 操作
function fetchData() {
fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => console.log("網路請求獲得的資料:", data)); // 進行網路請求
}
fetchData();
// 改變傳入參數
function addElement(arr, element) {
arr.push(element); // 修改傳入的陣列
}
const myArray = [1, 2, 3];
addElement(myArray, 4);
console.log("修改後的陣列:", myArray); // [1, 2, 3, 4]
這些副作用都會對函式外部的狀態產生某種改變,這會使程式變得難以除錯和維護。
useEffect
在 React 開發中,useEffect
是一個非常重要的 Hook,用來處理副作用 (side effects)。它的主要功能是在組件渲染後執行一些會影響外部環境的操作(如發送網路請求、修改 DOM 等),這有助於將副作用邏輯與渲染邏輯分離,讓程式碼更加清晰且易於維護。
useEffect
的使用非常簡單,通常為以下幾個步驟:
useEffect
useEffect
函式中
useEffect
首先,我們需要從 React 中引入 useEffect
,這樣才能在功能組件中使用它。
import { useEffect } from 'react';
useEffect
函式中useEffect
會在組件渲染完成後被執行,在這個函式中,你可以放入所有需要在渲染後執行的副作用操作。
useEffect(() => {
//...要執行的 effect
});
這個函式中的邏輯會在組件渲染完畢後自動執行,適合用來處理需要在畫面顯示後進行的操作。
useEffect
的第二個參數是一個陣列,稱為依賴項 (dependencies)。當陣列中的依賴項發生變化時,useEffect
中的函式才會重新執行。這樣可以避免不必要的重複執行,從而提升效能。
useEffect(() => {
//...要執行的 effect
}, [dependencies]);
如果你傳入了一個空陣列 []
,useEffect
只會在組件首次渲染時執行一次。
useEffect
的四種使用方式
useEffect(() => {
console.log("mounted");
}, [])
這種方式只在組件初次渲染後執行一次。使用這種方法時,我們將 useEffect
的依賴性陣列設為空,表示它不依賴於任何外部值,因此只會執行一次。
useEffect(() => {
console.log("updated");
})
這種方式會在每次組件更新後執行。這種方法非常適合用來處理需要在每次渲染後進行的操作。
useEffect(() => {
console.log("updated with dependencies");
}, [count])
在這種情況下,useEffect
只有在指定的依賴項(例如 count
)發生變更時才會執行。這樣可以避免在每次渲染時都執行昂貴的計算,從而提升效能。
useEffect(() => {
const onMousedown = () => {
console.log("mousedown");
};
window.addEventListener("mousedown", onMousedown);
const timer = setInterval(() => {
console.log('Hello React');
}, 1000);
return () => {
console.log("cleanup");
window.removeEventListener("mousedown", onMousedown);
clearInterval(timer);
};
});
在這個例子中,useEffect
返回了一個清理函式,用於在組件重新渲染或卸載時清除副作用。如果不清理這些副作用,可能會導致記憶體洩漏或性能問題。
useEffect
的常見應用情境如下:addEventListener
/removeEventListener
):為避免重複監聽事件,在組件掛載後新增事件監聽器,並在組件卸載前移除。setInterval
/clearInterval
):避免重複設置定時器,通常在組件掛載後設置,並在組件卸載前清除。副作用是 JavaScript 和其他程式語言中的一個關鍵概念。理解並有效地管理副作用有助於撰寫更穩健和可預測的程式碼。在 React 中,useEffect
提供了一個好的方式來處理副作用,使得組件的生命週期管理更加簡單。透過合理使用 useEffect
,我們可以確保程式邏輯和副作用邏輯保持分離,從而提升應用程式的可維護性和效能。